Make DB snapshot commit errors include active methods
authorAaron Schulz <aschulz@wikimedia.org>
Wed, 14 Sep 2016 17:09:36 +0000 (10:09 -0700)
committerAaron Schulz <aschulz@wikimedia.org>
Fri, 16 Sep 2016 00:35:55 +0000 (00:35 +0000)
Change-Id: I59e501528b104e797b36103fa18792f539d92a14

includes/db/Database.php

index 6cfff0e..3374d67 100644 (file)
@@ -618,6 +618,25 @@ abstract class DatabaseBase implements IDatabase, LoggerAwareInterface {
                return $this->mTrxLevel ? $this->mTrxWriteCallers : [];
        }
 
+       protected function pendingWriteAndCallbackCallers() {
+               if ( !$this->mTrxLevel ) {
+                       return [];
+               }
+
+               $fnames = $this->mTrxWriteCallers;
+               foreach ( [
+                       $this->mTrxIdleCallbacks,
+                       $this->mTrxPreCommitCallbacks,
+                       $this->mTrxEndCallbacks
+               ] as $callbacks ) {
+                       foreach ( $callbacks as $callback ) {
+                               $fnames[] = $callback[1];
+                       }
+               }
+
+               return $fnames;
+       }
+
        public function isOpen() {
                return $this->mOpened;
        }
@@ -3042,9 +3061,10 @@ abstract class DatabaseBase implements IDatabase, LoggerAwareInterface {
        public function flushSnapshot( $fname = __METHOD__ ) {
                if ( $this->writesOrCallbacksPending() || $this->explicitTrxActive() ) {
                        // This only flushes transactions to clear snapshots, not to write data
+                       $fnames = implode( ', ', $this->pendingWriteAndCallbackCallers() );
                        throw new DBUnexpectedError(
                                $this,
-                               "$fname: Cannot COMMIT to clear snapshot because writes are pending."
+                               "$fname: Cannot COMMIT to clear snapshot because writes are pending ($fnames)."
                        );
                }
 
@@ -3511,9 +3531,10 @@ abstract class DatabaseBase implements IDatabase, LoggerAwareInterface {
        public function getScopedLockAndFlush( $lockKey, $fname, $timeout ) {
                if ( $this->writesOrCallbacksPending() ) {
                        // This only flushes transactions to clear snapshots, not to write data
+                       $fnames = implode( ', ', $this->pendingWriteAndCallbackCallers() );
                        throw new DBUnexpectedError(
                                $this,
-                               "$fname: Cannot COMMIT to clear snapshot because writes are pending."
+                               "$fname: Cannot COMMIT to clear snapshot because writes are pending ($fnames)."
                        );
                }
 
@@ -3650,18 +3671,11 @@ abstract class DatabaseBase implements IDatabase, LoggerAwareInterface {
                if ( $this->mTrxLevel && $this->mTrxDoneWrites ) {
                        trigger_error( "Uncommitted DB writes (transaction from {$this->mTrxFname})." );
                }
-               $danglingCallbacks = array_merge(
-                       $this->mTrxIdleCallbacks,
-                       $this->mTrxPreCommitCallbacks,
-                       $this->mTrxEndCallbacks
-               );
-               if ( $danglingCallbacks ) {
-                       $callers = [];
-                       foreach ( $danglingCallbacks as $callbackInfo ) {
-                               $callers[] = $callbackInfo[1];
-                       }
-                       $callers = implode( ', ', $callers );
-                       trigger_error( "DB transaction callbacks still pending (from $callers)." );
+
+               $danglingWriters = $this->pendingWriteAndCallbackCallers();
+               if ( $danglingWriters ) {
+                       $fnames = implode( ', ', $danglingWriters );
+                       trigger_error( "DB transaction writes or callbacks still pending ($fnames)." );
                }
        }
 }